<?php
/**
 * Created by PhpStorm.
 * User: lf
 * Date: 2018/8/15
 * Time: 下午11:30
 */
namespace api\behaviors;

use common\config\AppConf;
use common\helpers\StringHelper;
use common\libs\Logger;
use Yii;
use yii\base\InvalidConfigException;
use yii\web\Response;

class ResponseFormatBehavior extends \yii\base\Behavior
{

    public function events()
    {
        return [
            Response::EVENT_BEFORE_SEND => [$this, 'beforeSend'],
        ];
    }
	
	/**
	 * 处理逻辑：系统级错误，就把rspno设置成response里的getStatusCode
	 * 当系统返回200code时，证明请求正确，此时就自定义程序的逻辑错误
	 */
    public function beforeSend()
    {
        $acceptTypes = Yii::$app->getRequest()->getAcceptableContentTypes();
        $types = array_keys( $acceptTypes );
        /** @var Response $response */
        $response = $this->owner;
	    $response->headers->add('Access-Control-Allow-Origin', '*');
	    $response->headers->add('Access-Control-Allow-Methods', 'POST,GET,OPTIONS,DELETE');
//	    p($response->data);
//	    pp($response->getStatusCode());
	    /**
	     * 解析单个数据查询的格式
	     */
	    try {
		    $response = $this->_parshSingle($response);
	    } catch (InvalidConfigException $e) {
		    Yii::error($e->getTraceAsString(),$e->getMessage());
	    }
	
	    /**
	     * 分开讨论请求成功和请求错误的情况
	     */
	    if($response->getStatusCode() !== 200){
		    $response = $this->_handleNot200($response);
	    }else{
		    $response = $this->_handleSuccessCode($response);
	    }
	    if ($response->data[AppConf::APP_NO] != AppConf::APP_NO_OK) {
		    Logger::info($response->data, '非正常返回数据为');
	    }
	    isset($types[0]) && $types[0] == 'text/html' && $response->format = Response::FORMAT_JSON;
    }
	
	/**
	 * 解析单个数据查询的格式，让数据放到rspdata内
	 * @param Response $response
	 * @return Response
	 * @throws InvalidConfigException
	 */
    private function _parshSingle($response){
	    $path_info = Yii::$app->request->getPathInfo();
	    $path_arr = explode('/',$path_info);
	    $end = end($path_arr);
	    if(is_numeric($end)){
		    $data = $response->data;
		    $response->data = [];
		    $response->data[AppConf::APP_DATA] = $data;
	    }
	    return $response;
    }
	
	/**
	 * 解析单个数据查询的格式，让数据放到rspdata内
	 * @param Response $response
	 * @return Response
	 */
    private function _handleNot200($response){
        if (Yii::$app->errorHandler->exception !== null) {
            Logger::warning($response->data,Yii::$app->errorHandler->exception->getMessage());//日志记录原本的错误信息，会入库，平时检测下库里的数据，用于发现问题
            Logger::error(Yii::$app->errorHandler->exception->getTraceAsString(),Yii::$app->errorHandler->exception->getMessage(),'AppException');//异常信息就在log日志里体现，用于定位问题
        }
	    if(!isset($response->data[AppConf::APP_DATA])){
		    $temp = $response->data;
		    $response->data = [];
		    $response->data[AppConf::APP_DATA] = $temp;
	    }
	    if($response->getStatusCode() == 401){
		    /**
		     * 未登录状态改成中文提示
		     */
		    $response->data[AppConf::APP_NO] = AppConf::APP_NO_AUTH;
		    $response->data[AppConf::APP_MSG] = '您尚未登录';
	    }elseif($response->getStatusCode() == 422){
		    /**
		     * 模型rules错误，单独处理
		     */
		    $response->data[AppConf::APP_NO] = AppConf::APP_NO_PARAM;
		    $response->data[AppConf::APP_MSG] = StringHelper::getErrorSummary($response->data[AppConf::APP_DATA]);
		    $response->data[AppConf::APP_DATA] = [];
	    }elseif($response->getStatusCode() == 429 || $response->getStatusCode() == 430){
            /**
             * 处理多次访问错误
             */
            $response->data[AppConf::APP_DATA] = [];
            $response->data[AppConf::APP_NO] = $response->getStatusCode();
            $response->data[AppConf::APP_MSG] = AppConf::$sysErrors[$response->getStatusCode()];
        }elseif($response->getStatusCode() != 200){
		    /**
		     * 如果不等于200，则统一处理成系统级错误
		     */
		    $response->data[AppConf::APP_DATA] = YII_DEBUG ? $response->data[AppConf::APP_DATA] : [];
		    $response->data[AppConf::APP_NO] = $response->getStatusCode();
		    $response->data[AppConf::APP_MSG] = AppConf::$sysErrors[$response->getStatusCode()];
	    }
	    return $response;
    }
	
	/**
	 * 处理正常请求的数据返回
	 * @param Response $response
	 * @return Response
	 */
    private function _handleSuccessCode($response){
	    /**
	     * 等于200时，设置好rspno，rspmsg，rspdata
	     */
	    $rsp[AppConf::APP_NO] = isset($response->data[AppConf::APP_NO]) ? @$response->data[AppConf::APP_NO] : AppConf::APP_NO_OK; //此处可以自定义rspno里面的东西
	    $rsp[AppConf::APP_MSG] = isset($response->data[AppConf::APP_MSG]) ? @$response->data[AppConf::APP_MSG] : AppConf::APP_MSG_OK; //此处可以自定义rspmsg里面的东西
	    if(empty($response->data) || !is_array($response->data)){
		    $response->data = [];
	    }
	    $response->data = array_merge($rsp,$response->data);
	    return $response;
    }
	
    //用来做行为的测试
	public function say()
	{
		echo 1;
	}
}